class Droite
{
	protected static final double EPSILON = 0.000001;
	protected double _a, _b, _c;

	protected static boolean almostEqual(double a, double b)
	{
		return (Math.abs(a-b) < EPSILON);
	}

	public Droite(double a, double b, double c)
	{
		if (almostEqual(a, 0) && almostEqual(b, 0))
			throw new IllegalArgumentException();
		else
		{
			_a = a;
			_b = b;
			_c = c;
		}
	}

	public Droite(Point a, Point b)
	{
		_a = a.getY()-b.getY();
		_b = b.getX()-a.getX();
		_c = _a*a.getX() + _b*a.getY();
		//throw new UnsupportedOperationException();
	}

	public static Droite create(Point p1, Point p2)
	{
		//dummy function...
		return new Droite(p1, p2);
	}

	public double getA()
	{
		return _a;
	}

	public double getB()
	{
		return _b;
	}

	public double getC()
	{
		return _c;
	}

	public boolean isHorizontal()
	{
		//equation: 0x+1y=const
		return almostEqual(_a, 0);
	}

	public boolean isVertical()
	{
		//equation: 1x+0y=const
		return almostEqual(_b, 0);
	}

	public Point intersection(Droite d)
	{
		double det = _a*d.getB() - d.getA()*_b;
		if (almostEqual(det, 0))
			return null;
		else
		{
			double x = _c*d.getB() - d.getC()*d.getA();
			double y = _a*d.getC() - d.getA()*_c;
			return new Point(x/det, y/det);
		}
	}
	
	public boolean contains(Point p)
	{
		return almostEqual(_a*p.getX() + _b*p.getY(), _c);
	}

	public boolean equals(Droite d)
	{
		Point p; //testing point
		if (!almostEqual(_b, 0)) p = new Point(0, _c/_b); //function
		else p = new Point(_c/_a, 0); //vertical
		return (this.intersection(d)==null && d.contains(p));
	}

	public String toString()
	{
		return String.valueOf(_a)+"x + "+String.valueOf(_b)+"y = "+String.valueOf(_c);
	}
}
